package tictactoe.GUI;

import tictactoe.Desk;
import tictactoe.Game;
import tictactoe.Player;
import tictactoe.multiplayer.client.Client;
import tictactoe.util.Constants;
import tictactoe.util.Score;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.util.ResourceBundle;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;

/**
 *
 * @author Home
 */
public class GameWindow extends javax.swing.JDialog {

    /**
     *
     */
    public static final int SINGLE = 1;
    /**
     *
     */
    public static final int MULTI = 2;
    private static final int SQUARE = 21;
    private Game game;
    private Score score;
    private Image crossImage, circleImage;
    private Client client;

    private GameWindow(Frame parent) {
        super(parent, true);
        crossImage = new ImageIcon(getClass().getResource("/tictactoe/GUI/zurag/cross_80px.PNG")).getImage();
        circleImage = new ImageIcon(getClass().getResource("/tictactoe/GUI/zurag/circle_80px.PNG")).getImage();
        crossImage = crossImage.getScaledInstance(20, 20, Image.SCALE_SMOOTH);
        circleImage = circleImage.getScaledInstance(20, 20, Image.SCALE_SMOOTH);
        initComponents();
    }

    /**
     *
     * @param parent
     * @param cross
     * @param circle
     * @param gamesCount
     */
    public GameWindow(Frame parent, Player cross, Player circle, int gamesCount) {
        this(parent);
        score = new Score(cross, circle, gamesCount);
        game = new Game(cross, circle);
        Desk d = game.getDeskCopy();
        playboard.setPreferredSize(new Dimension(d.getWidth() * SQUARE, d.getHeight() * SQUARE));
        crossName.setText(cross.getName());
        circleName.setText(circle.getName());
        crossScore.setText(Integer.toString(score.getCrossPoints()));
        circleScore.setText(Integer.toString(score.getCirclePoints()));
        highlightCurrentPlayer();
        pack();

    }

    /**
     *
     * @param parent
     * @param client
     * @param cross
     * @param circle
     * @param gamesCount
     */
    public GameWindow(Frame parent, Client client, Player cross, Player circle, int gamesCount) {
        this(parent, cross, circle, gamesCount);
        this.client = client;
        System.out.println("Alive: " + client.isAlive());
        System.out.println("Connected: " + client.isConnected());
    }

    /**
     *
     * @return
     */
    public Game getGame() {
        return game;
    }

    @Override
    public void repaint() {
        super.repaint();
        highlightCurrentPlayer();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        if (game != null) {
            int dx = playboard.getLocationOnScreen().x - getLocationOnScreen().x;
            int dy = playboard.getLocationOnScreen().y - getLocationOnScreen().y;

            g.setColor(Color.white);
            g.fillRect(0 + dx, 0 + dy, playboard.getWidth(), playboard.getHeight());
            g.setColor(Color.black);
            Desk d = game.getDeskCopy();
            for (int i = 0; i <= d.getWidth(); i++) {
                int x = i * SQUARE + dx;
                g.drawLine(x, 0 + dy, x, playboard.getHeight() + dy);
            }
            for (int i = 0; i <= d.getHeight(); i++) {
                int y = i * SQUARE + dy;
                g.drawLine(0 + dx, y, playboard.getWidth() + dx, y);
            }

            for (Point p : d.getCircles()) {
                drawCircle(g, p);
            }

            for (Point p : d.getCrosses()) {
                drawCross(g, p);
            }
        }
    }

    /**
     *
     * @param p
     */
    public void remoteTurn(Point p) {
        turn(p, false);
    }

    private void turn(Point p, boolean local) {
        int playing = game.getPlaying();

        if (local) {
            if (game.getCircle().getType() != Player.TYPE_HUMAN && playing == Constants.CIRCLE) {
                return;
            }
            if (game.getCross().getType() != Player.TYPE_HUMAN && playing == Constants.CROSS) {
                return;
            }
        } else {
            if (game.getCross().getType() != Player.TYPE_REMOTE && playing == Constants.CROSS) {
                return;
            }
            if (game.getCircle().getType() != Player.TYPE_REMOTE && playing == Constants.CIRCLE) {
                return;
            }
        }

        if (game.turn(p)) {
            switch (playing) {
                case Constants.CIRCLE:
                    drawCircle(getGraphics(), p);
                    break;
                case Constants.CROSS:
                    drawCross(getGraphics(), p);
                    break;
            }
            if (local) {
                client.move(p);
                //end bi darsan bolno. buya
                }
            highlightCurrentPlayer();
            turns.setText(Integer.toString((game.getTurnCount() + 1) / 2));
            checkWinner();
        }
    }

    private void drawCross(Graphics g, Point bairlal) {
        int dx = playboard.getLocationOnScreen().x - getLocationOnScreen().x;
        int dy = playboard.getLocationOnScreen().y - getLocationOnScreen().y;
        g.setColor(Color.blue);
        int x1 = bairlal.x * SQUARE + 1 + dx;
        int y1 = bairlal.y * SQUARE + 1 + dy;
        if (crossImage != null) {
            g.drawImage(crossImage, x1, y1, null);
        } else {
            x1++;
            y1++;
            int x2 = bairlal.x * SQUARE + 18 + dx;
            int y2 = bairlal.y * SQUARE + 18 + dy;
            g.drawLine(x1, y1, x2, y2);
            g.drawLine(x2, y1, x1, y2);
        }
    }

    private void drawCircle(Graphics g, Point where) {
        int dx = playboard.getLocationOnScreen().x - getLocationOnScreen().x;
        int dy = playboard.getLocationOnScreen().y - getLocationOnScreen().y;
        g.setColor(Color.red);
        int x = where.x * SQUARE + 1 + dx;
        int y = where.y * SQUARE + 1 + dy;
        if (circleImage != null) {
            g.drawImage(circleImage, x, y, null);
        } else {
            int width = 16;
            int height = 16;
            g.drawOval(x + 2, y + 2, width, height);
        }
    }

    /**
     * end yalagchiig shalgana.
     */
    private void checkWinner() {
        if (game.getWinnerPlayer() != null) {
            String msg = ResourceBundle.getBundle("tictactoe/GUI/texts").getString("winnerIs");
            msg = msg.replace("NAME", game.getWinnerPlayer().getName());
            JOptionPane.showMessageDialog(this, msg);
            score.add(game);
            crossScore.setText(Integer.toString(score.getCrossPoints()));
            circleScore.setText(Integer.toString(score.getCirclePoints()));
            if (score.gamesRemaining() > 0) {
                game = new Game(game.getCross(), game.getCircle(), game.getPlaying());
                highlightCurrentPlayer();
                repaint();
            } else {
                game = null;
                Stats s = new Stats(JOptionPane.getFrameForComponent(this), score);
                s.setLocation(getLocation());
                setVisible(false);
                s.setVisible(true);
                setLocation(s.getLocation());
            }
        }
    }

    private void highlightCurrentPlayer() {
        switch (game.getPlaying()) {
            case Constants.CROSS:
                crossPanel.setBackground(UIManager.getColor("textHighlight"));
                circlePanel.setBackground(UIManager.getColor("control"));
                break;
            case Constants.CIRCLE:
                circlePanel.setBackground(UIManager.getColor("textHighlight"));
                crossPanel.setBackground(UIManager.getColor("control"));
                break;
        }
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        playboard = new javax.swing.JPanel();
        stats = new javax.swing.JPanel();
        crossPanel = new javax.swing.JPanel();
        cross = new CrossPanel();
        crossName = new javax.swing.JLabel();
        crossScore = new javax.swing.JLabel();
        circlePanel = new javax.swing.JPanel();
        circle = new CirclePanel();
        circleName = new javax.swing.JLabel();
        circleScore = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        turns = new javax.swing.JLabel();

        setLocationByPlatform(true);
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosed(java.awt.event.WindowEvent evt) {
                formWindowClosed(evt);
            }
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        playboard.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                turn(evt);
            }
        });

        javax.swing.GroupLayout playboardLayout = new javax.swing.GroupLayout(playboard);
        playboard.setLayout(playboardLayout);
        playboardLayout.setHorizontalGroup(
            playboardLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 250, Short.MAX_VALUE)
        );
        playboardLayout.setVerticalGroup(
            playboardLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        getContentPane().add(playboard, java.awt.BorderLayout.CENTER);

        stats.setMaximumSize(new java.awt.Dimension(150, 32767));
        stats.setMinimumSize(new java.awt.Dimension(150, 0));
        stats.setPreferredSize(new java.awt.Dimension(150, 276));

        cross.setMaximumSize(new java.awt.Dimension(20, 20));
        cross.setMinimumSize(new java.awt.Dimension(20, 20));

        javax.swing.GroupLayout crossLayout = new javax.swing.GroupLayout(cross);
        cross.setLayout(crossLayout);
        crossLayout.setHorizontalGroup(
            crossLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 20, Short.MAX_VALUE)
        );
        crossLayout.setVerticalGroup(
            crossLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 20, Short.MAX_VALUE)
        );

        crossName.setText("Cross player");

        crossScore.setText("0");

        javax.swing.GroupLayout crossPanelLayout = new javax.swing.GroupLayout(crossPanel);
        crossPanel.setLayout(crossPanelLayout);
        crossPanelLayout.setHorizontalGroup(
            crossPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(crossPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(cross, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(crossName)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 14, Short.MAX_VALUE)
                .addComponent(crossScore)
                .addContainerGap())
        );
        crossPanelLayout.setVerticalGroup(
            crossPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(crossPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(crossPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(crossPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(crossName)
                        .addComponent(crossScore))
                    .addComponent(cross, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        circle.setMaximumSize(new java.awt.Dimension(20, 20));
        circle.setMinimumSize(new java.awt.Dimension(20, 20));
        circle.setPreferredSize(new java.awt.Dimension(20, 20));

        javax.swing.GroupLayout circleLayout = new javax.swing.GroupLayout(circle);
        circle.setLayout(circleLayout);
        circleLayout.setHorizontalGroup(
            circleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 20, Short.MAX_VALUE)
        );
        circleLayout.setVerticalGroup(
            circleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 20, Short.MAX_VALUE)
        );

        circleName.setText("Circle player");

        circleScore.setText("0");

        javax.swing.GroupLayout circlePanelLayout = new javax.swing.GroupLayout(circlePanel);
        circlePanel.setLayout(circlePanelLayout);
        circlePanelLayout.setHorizontalGroup(
            circlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(circlePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(circle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(circleName)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE)
                .addComponent(circleScore)
                .addContainerGap())
        );
        circlePanelLayout.setVerticalGroup(
            circlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(circlePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(circlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(circlePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(circleName)
                        .addComponent(circleScore))
                    .addComponent(circle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("tictactoe/GUI/texts"); // NOI18N
        jLabel2.setText(bundle.getString("turns")); // NOI18N

        javax.swing.GroupLayout statsLayout = new javax.swing.GroupLayout(stats);
        stats.setLayout(statsLayout);
        statsLayout.setHorizontalGroup(
            statsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(statsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, statsLayout.createSequentialGroup()
                        .addComponent(jLabel2)
                        .addGap(10, 10, 10)
                        .addComponent(turns, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(circlePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(crossPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        statsLayout.setVerticalGroup(
            statsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statsLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(crossPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(circlePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 174, Short.MAX_VALUE)
                .addGroup(statsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(turns, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        getContentPane().add(stats, java.awt.BorderLayout.EAST);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void turn(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_turn
        if (game != null && game.getWinnerPlayer() == null) {
            Point p = evt.getPoint();
            p.x /= 21;
            p.y /= 21;
            turn(p, true);
        }
    }//GEN-LAST:event_turn

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        if (client != null) {
            client.disconnect();
        }
    }//GEN-LAST:event_formWindowClosing

    private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
        // TODO add your handling code here:
        System.err.println("game window dotor tavisan windowClosed method");
    }//GEN-LAST:event_formWindowClosed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel circle;
    private javax.swing.JLabel circleName;
    private javax.swing.JPanel circlePanel;
    private javax.swing.JLabel circleScore;
    private javax.swing.JPanel cross;
    private javax.swing.JLabel crossName;
    private javax.swing.JPanel crossPanel;
    private javax.swing.JLabel crossScore;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel playboard;
    private javax.swing.JPanel stats;
    private javax.swing.JLabel turns;
    // End of variables declaration//GEN-END:variables

    //JPanel extension to draw necessary images
    private class CrossPanel extends JPanel {

        @Override
        public void paint(Graphics g) {
            super.paint(g);

            if (crossImage != null) {
                g.drawImage(crossImage, 0, 0, null);
            } else {
                g.drawLine(2, 2, 16, 16);
                g.drawLine(2, 16, 16, 2);
            }
        }
    }

    private class CirclePanel extends JPanel {

        @Override
        public void paint(Graphics g) {
            super.paint(g);

            if (crossImage != null) {
                g.drawImage(circleImage, 0, 0, null);
            } else {
                g.drawOval(2, 2, 16, 16);
            }
        }
    }
}
